#pragma once

#include <map>
#include <set>

#include "base/core/singleton.h"
#include "base/core/object_pool.h"
#include "Common/MissionDefine.h"
#include "Common/ComTypeDefine.h"
#include "base/core/csv_parser.h"
#include "Common/CharacterDefine.h"

class Player;
class MissionPart;
//通过移位组合动态任务text表条件 text 表中 目标场景(4Byte)+任务类型(1Byte)+完成条件(20bit)+阵营类型(4bit)
#define DY_MISSION_TEXT_KEY(mapid,type,cond,camp) ((mapid << 31) | (type << 23) | (cond << 3) | camp)
#define DY_MISSION_TEXT_MAP(key) (key >> 31)
#define DY_MISSION_TEXT_TYPE(key) ((key & 0x7F800000) >> 23)
#define DY_MISSION_TEXT_COND(key) ( (key & 0x7FFFF8) >> 3)
#define DY_MISSION_TEXT_CAMP(key) (key &0x7)

/**
*@brief 任务管理器单例
*@brief
*/

class MissionManager : public ManualSingleton<MissionManager>
{
public:
	typedef std::unordered_map<uint32_t, uint32_t>				Map;
	typedef std::unordered_set<uint32_t>						Set;
	typedef std::vector<int32_t>								Vector;
	typedef std::unordered_map<uint32_t, SET_UINT32 >			MissionListMap;
	typedef std::unordered_map<uint32_t, MissionInfo* >			MissionInfoMap;
	typedef std::unordered_map<uint32_t, MissionChapterInfo>	MissionChapterInfoMap;
	typedef std::unordered_map<uint32_t, Set >					Tabal;
	typedef std::unordered_map<uint32_t, Set >					WithoutPreConMissionsMap;
	//
	typedef std::unordered_map<uint32_t, DyMissionInfo> DyMissionInfoMap;
	typedef std::unordered_map<uint32_t, DyConditionInfo> DyCondtionInfoMap;
public:
	MissionManager();
	virtual ~MissionManager();

public:
	bool						Init();
	bool						UnInit();
	MissionInfo*				FindMissionInfoById(const uint32_t& missionId);
	bool						IsOptionalParentMission(uint32_t parentMissionId);															//是否是分支任务的父任务
	bool						IsOptionalSonMission(uint32_t parentMissionId, uint32_t sonMissionId);										//是否是分支子任务
	const SET_UINT32 *			GetOptionSonMission(uint32_t parentMissionId);																//获取一个分支所有子任务的服任务
	uint32_t					GetBelonToOption(uint32_t sonMissionId);																	//获取一个分支子任务的服任务
	ProtoBuf::ERetCode			OnUpdateAcceptable(Player* pPlayer, std::unordered_set<uint32_t>& missionList);								//更新可接任务列表
	const SET_UINT32*			FindPostList(const uint32_t& preCon);																		//返回后置任务列表
	Set*						FindHeadList(const uint32_t& missionId);																	//查找这个任务所在线的第一个任务
	WithoutPreConMissionsMap&	FindMissionListWithoutPreCon();																				//返回没有前置的任务列表
	uint32_t					BountyFreshItemID();	//赏金任务刷新道具ID
	uint32_t					BountyMaxAcceptNum();	//赏金任务周期内最大接取次数
	uint32_t					GetFirstChapter(int32_t camp, int32_t race);

	///////////////////////////////////新任务接口///////////////////////////////////////
	//获取可接任务列表(主支线)
	int32_t	OnCanAccept(Player* pPlayer, SET_UINT32& missionList, int32_t recvType /*= M_RECEIVE_TYPE_USER*/);
	int32_t CanAccept(Player *pPlayer, uint32_t missionId, bool reacceptFlag);
	int32_t CanAccept(Player *pPlayer, MissionInfo *pMissionInfo, bool reacceptFlag);
	int32_t CanAccept(Player *pPlayer, const AcceptInfo &cond,SCanAcceptParam &param);
	//阵营任务判断工会和队伍
	int32_t CanAcceptEx(Player *pPlayer, MissionInfo *pMissionInfo);
	//是否能接取动态任务 dyCfgId:动态任务的配置ID
	int32_t CanAcceptDy(Player *pPlayer, uint32_t dyCfgId);
	int32_t CanAcceptDy(Player *pPlayer, const DyMissionInfo *pDyMissionInfo);
	int32_t CanAcceptDy(Player *pPlayer, MissionTrack *pMissionTrack);
	//接取任务 reacceptFlag:是否是重新接取标志
	int32_t OnAccept(Player* pPlayer, uint32_t missionId, bool notify, bool reacceptFlag = false);
	//GM接取任务
	int32_t OnGMAccept(Player* pPlayer, uint32_t missionId, bool notify);
	//接取动态任务
	int32_t OnAcceptDy(Player* pPlayer, uint32_t missionId, bool notify);
	int32_t OnAcceptDy(Player* pPlayer, MissionTrack *pMissionTrack, bool notify);
	//提取任务条件
	int32_t OnExtractCond(Player* pPlayer, uint32_t missionId, std::vector<ItemInfo> &conds);
	int32_t OnExtractCond(Player* pPlayer, MissionInfo *pMissionInfo, std::vector<ItemInfo> &conds);
	//提取动态任务条件
	int32_t OnExtractDyCond(Player* pPlayer, uint32_t missionId, std::vector<ItemInfo> &conds,uint32_t &textId,bool preUpdate = true);
	int32_t OnExtractDyCond(Player* pPlayer, const DyMissionInfo *pDyMissionInfo, std::vector<ItemInfo> &conds, uint32_t &textId, bool preUpdate = true);
	//条件预更新进度(有些条件接取任务时就已经完成了)
	void	OnPreUpdateProgress(Player *pPlayer, ItemInfo &cond);
	//更新任务进度
	int32_t OnUpdateProgress(Player *pPlayer, uint32_t missionId, const ExecuteData& data);
	//更新条件进度
	void	OnUpdateCondProcess(const ExecuteData& data, ItemInfo &cond,bool &notify);
	//提交任务 selidx:可选奖励索引
	int32_t OnSubmit(Player* pPlayer, uint32_t missionId, uint32_t selidx);
	//提交动态任务
	int32_t OnSubmitDy(Player* pPlayer, uint32_t dymissionId);
	//放弃任务
	int32_t OnAbandon(Player* pPlayer, uint32_t missionId);
	//放弃动态任务
	int32_t OnAbandonDy(Player* pPlayer, uint32_t dymissionId,bool notify);
	//移除任务
	int32_t RemoveMission(Player* pPlayer, MissionInfo* pMissionInfo);
	//移除任务
	int32_t RemoveMission(Player *pPlayer, MissionTrack *pMissinTrack, MissionInfo* pMissionInfo);
	//移除动态任务
	int32_t RemoveDyMission(Player* pPlayer, uint32_t dymissionId,bool notify);
	//提取动态任务属性奖励
	int32_t OnExtractDyAttrReward(Player* pPlayer,MissionTrack *pNewMissinTrack);
	//动态任务奖励
	int32_t OnAddDyMissionReward(Player *pPlayer, int32_t missionType, MAP_INT32_INT32 &mapAttrReward, int32_t loopCount, int32_t rate);
	//添加任务掉落
	int32_t OnAddMissionDrop(CharIDType cid, MissionPart *pMissionPart,MissionTrack *pMissionTrack,int32_t progressLev);
	//移除任务掉落
	int32_t OnDelMissionDrop(Player* pPlayer, MissionTrack *pMissionTrack);
	//移除任务物品
	int32_t OnDelMissionItem(Player* pPlayer, MissionTrack *pMissionTrack);
	//生成任务条件
	int32_t OnGeneralCond(Player* pPlayer, const DyMissionInfo *pDyMissionInfo, const DyConditionInfo *pDyConditionInfo, ItemInfo &cond,uint32_t &textId);
	//生成杀怪条件
	int32_t OnGeneralKillMonsCond(Player* pPlayer, const DyMissionInfo *pDyMissionInfo, const DyConditionInfo *pDyConditionInfo, uint32_t mapId, int32_t campParam, ItemInfo &cond);
	//生成杀怪追踪区域
	int32_t OnGeneralKillMonsAreaCond(Player* pPlayer, const DyMissionInfo *pDyMissionInfo, const DyConditionInfo *pDyConditionInfo, uint32_t mapId, int32_t campParam, ItemInfo &cond);
	//生成对话NPC条件
	int32_t OnGeneralTalkCond(Player* pPlayer, const DyMissionInfo *pDyMissionInfo, const DyConditionInfo *pDyConditionInfo, uint32_t mapId, int32_t campParam, ItemInfo &cond);
	//生成收集物品条件 
	int32_t OnGeneralCollectItemCond(Player* pPlayer, const DyMissionInfo *pDyMissionInfo, const DyConditionInfo *pDyConditionInfo,ItemInfo &cond);
	//生成前端采集条件
	int32_t OnGeneralClientCollectCond(Player* pPlayer, const DyMissionInfo *pDyMissionInfo, const DyConditionInfo *pDyConditionInfo, uint32_t mapId, int32_t campParam, ItemInfo &cond);
	//生成采集场景物件条件 
	int32_t OnGeneralCollectMonsCond(Player* pPlayer, const DyMissionInfo *pDyMissionInfo, const DyConditionInfo *pDyConditionInfo, uint32_t mapId, int32_t campParam, ItemInfo &cond);
	//生成 行为按钮条件
	int32_t OnGeneralActionButtonCond(Player* pPlayer, const DyMissionInfo *pDyMissionInfo, const DyConditionInfo *pDyConditionInfo, uint32_t mapId, int32_t campParam, ItemInfo &cond);
	//生成 使用场景物件条件
	int32_t OnGeneralUseThingCond(Player* pPlayer, const DyMissionInfo *pDyMissionInfo, const DyConditionInfo *pDyConditionInfo, uint32_t mapId, int32_t campParam, ItemInfo &cond);
	//生成 提交物品的条件
	int32_t OnGeneralSubmitItemCond(Player* pPlayer, const DyMissionInfo *pDyMissionInfo, const DyConditionInfo *pDyConditionInfo, ItemInfo &cond);
	//生成 提交装备的条件
	int32_t OnGeneralSubmitEquipCond(Player* pPlayer, const DyMissionInfo *pDyMissionInfo, const DyConditionInfo *pDyConditionInfo, ItemInfo &cond);


	//动态随机地图阵营生物 creatureKind:生物类型，1-怪物，2-npc,3-可采集物件，4-可使用物件，5-区域
	int32_t DyRandMapCampCreature(uint32_t mapId, int32_t campParam,int32_t creatureKind,uint32_t &cfgId);
	//随机没有地图归属的怪物 paramType:参数类型
	uint32_t DyRandNoMapMons(CharIDType cid, int32_t missionType, int32_t paramType);
	//根据区域 动态随机前端采集物ID
	int32_t DyRandClientCollectThingByArea(uint32_t areaId, uint32_t &collectThingId);
	//根据类型 动态随机参数 type:类型，1-随机物品(paramA:物品ID)，2-采集物(paramA:物品ID)，3-怪物(paramA:物品ID),4-行为按钮(paramA 按钮ID)   typeVal:类型值
	int32_t DyRandParamByType(int32_t type, uint32_t typeKey, int32_t missionType, uint32_t &paramA, uint32_t &paramB);
	//根据任务类型 动态随机物品ID和数量
	int32_t DyRandItemNum(int32_t missionType, int32_t level, uint32_t &itemId, int32_t &itemNum);
	//根据任务类型 动态随机装备ID
	int32_t DyRandEquip(int32_t missionType, int32_t minLev, int32_t maxLev, uint32_t &itemId);

	//获取任务最大环数
	int32_t DyMaxCount(int32_t missionType, int32_t level);
	//根据任务类型随机一个任务ID
	int32_t DyRandMissionId(Player *pPlayer, int32_t missionType);
	//随机任务
	int32_t DyRandMissionTrackByType(Player *pPlayer, int32_t missionType, MissionTrack *pMissionTrack);
	//设置任务proto信息
	bool SetMissionTrackProto(MissionTrack *pMissionTrack, CharacterDBMissionTrack &missionProto);
	bool SetMissionTrackProto(MissionTrack *pMissionTrack, CMissionTrack &missionProto);
	//从任务proto拷贝信息
	bool CopyFromMissionProto(MissionTrack *pMissionTrack, const CharacterDBMissionTrack &missionProto);
	//////////////////////////////////////////////////////////////////////////





	//任务奖励
	void						AddReward(Player* pPlayer, int32_t kind, TASK_REWARD& reward, float ration = 1);											//增加任务奖励
	bool						RemoveReward(Player* pPlayer, TASK_REWARD& reward);															//删除任务数据
	MissionInfo*				GetMissionCfgInfo(uint32_t missionId);
	const MissionChapterInfo*	GetMissionChapterCfgInfo(uint32_t chapterId);																//获取任务章节配置信息
	const DyMissionInfo*		GetDyMissionCfgInfo(uint32_t missionId);
	const DyConditionInfo*		GetDyConditionCfgInfo(uint32_t condId);
	const SET_UINT32*			GetDyMissionLstByType(int32_t missionType);
	uint32_t					GetDyTextId(uint64_t key);

	
	void						TriggerOut(Player *pPlayer,uint32_t chapterId);																//完成任务触发外部系统（活跃度，成就等）
	bool						ValidMissionType(int32_t missionType);	//是否是有效的任务类型
	const SET_INT32 &			AllMissionType();						//所有的任务类型
	bool						ValidCompleteType(int32_t completeType);//是否是有效的完成条件类型
	bool						ValidDyCompleteType(int32_t completeType);//是否是有效的动态完成条件类型
	bool						IsDyCompleteTypeNeedMap(int32_t completeType);//动态完成条件类型是否需要配置地图
public: //对象管理分配
	MissionInfo*				AllocMissionInfo();
	MissionTrack*				AllocMissionTrack();
	void						FreeMissionTrack(MissionTrack* pMissionTrack);

public:
	//解析接取条件(公用接口)
	bool						ParseAcceptCond(AcceptInfo &accept, std::string strAcceptParam, SParaseAcceptParam &param);
private:
	void						CreatMissionEntry(MissionInfo* pMissionInfo);																//创建任务单元
	void						CreateTabal(const uint32_t& zeroMissionId);																	//
	bool						LoadConfig(const char *szCfgFile);//初始化配置表信息
	bool						LoadChapter(const char *szCfgFile);//加载任务章节表
	bool						ProcessDyMission();//处理动态任务配置
	bool						ProcessDyCondition();//处理动态条件
	bool						ProcessDyText();	//处理动态任务前端显示
	uint64_t					ComposeTextKey(uint32_t mapId, int32_t missionType, int32_t condType, int32_t camp);						//组装text表的key

	void						ParseChapterReward(uint32_t chapterId, vector<TaskComplex> &reward, string strParam);												//解析章节奖励
	bool						ParseChapterCond(MissionChapterInfo &info, std::string strParam);											//解析任务接取条件
	bool						ParseTaskExecute(MissionInfo* pMissionInfo, std::string sExecute);											//解析任务完成条件
	void						ParseTaskRecereMove(MissionInfo* pMissionInfo, std::string sReceremove);
	void						ParseTaskReceAdd(MissionInfo* pMissionInfo, std::string sReceAdd);
	void						ParseTaskSubAward(MissionInfo* pMissionInfo, std::string sSubAward);
	void						ParseTaskSubAwardRand(MissionInfo* pMissionInfo, std::string sSubAwardRand);
	void						ParseTaskSubRemove(MissionInfo* pMissionInfo, std::string sSubRemove);
	void						ParseTaskFailType(MissionInfo* pMissionInfo, std::string sFailType);
	void						ParseTaskFailRemove(MissionInfo* pMissionInfo, std::string sFailRemove);
	void						ParseTaskReceEffect(MissionInfo* pMissionInfo, std::string receEffect);
	void						ParseTaskSubEffect(MissionInfo* pMissionInfo, std::string subEffect);
	void						InitTriggerOut();	//初始化任务外部类型触发外部系统对应类型	
	void						ParseTaskOutType(MissionChapterInfo &info, std::string sOutType);
private:
	bool						ProcessMapData(); //处理动态任务相关的地图数据
	bool						ProcessItemData();//处理动态任务相关的物品数据
	bool						ProcessEquipData();//处理动态任务相关的装备数据
	bool						ProcessBoxData();//处理动态任务相关的box数据
	bool						ProcessButtonData();//处理动态任务相关的行为按钮数据	
	bool						CheckFirstChapter();//检查第一个主线章节ID
public:
	//阵营任务
	uint32_t					GetCampMissionBaseConfig(std::string parmeter);
	void						GetCampMissionNumConfig(int32_t level, int32_t camp,int32_t &blueNum, int32_t &greenNum, int32_t &whiteNum);
	uint32_t					GetCampBoxId(uint32_t level, uint32_t camp);

public:
	//日常任务
	uint32_t					GetLoopMissionBaseConfig(std::string parmeter);
	void						GetLoopBaseReward(MAP_INT32_INT32 &mapAttrReward, uint32_t loopCount, int64_t level, int64_t upgradeExp);//获取任务基础奖励
	void						GetCampBaseReward(MAP_INT32_INT32 &mapAttrReward, int32_t level,int32_t quality);							//获取阵营任务基础奖励
	void						GetBountyBaseReward(MAP_INT32_INT32 &mapAttrReward, int32_t level, int32_t quality);						//获取赏金任务基础奖励
	void						GetGuildSpecialReward(uint32_t &boxId,int32_t loopCount);													//获取工会指定环奖励
	void						GetLoopSpecialReward(uint32_t &boxId, int32_t loopCount);													//获取指定环奖励
public://工会任务
	uint32_t					GetGuildMissionBaseConfig(std::string parmeter);															//获取工会任务最大环数
	void						GetGuildBaseReward(MAP_INT32_INT32 &mapAttrReward, uint32_t loopCount, int32_t curLevel,int32_t vaultLevel);//获取工会任务基础奖励
	void						GetGuildSpecialReward(std::vector<TaskComplex>& baseReward, uint32_t loopCount);							//获取工会指定环奖励

	//工会日常任务
	void						GetGuildDailyBaseReward(MAP_INT32_INT32 &mapAttrReward, int32_t level, int32_t officeLev,int32_t loopCount);	//获取工会日常任务基础奖励
	int32_t					    GetGuildDailyRewardMulti(int32_t loopCount);												//获取工会日常任务多倍奖励的倍率
	uint32_t					GetGuildDailyRandBoxReward(int32_t loopCount);												//获取工会日常任务随机宝箱奖励

	//日常任务
	void						GetDailyBaseReward(MAP_INT32_INT32 &mapAttrReward, int32_t level,int32_t loopCount);							//获取日常任务基础奖励
	int32_t					    GetDailyRewardMulti(int32_t loopCount);														//获取日常任务多倍奖励的倍率
	uint32_t					GetDailyRandBoxReward(int32_t loopCount);													//获取日常任务随机宝箱奖励

	//活动收集任务
	void						GetActBaseReward(MAP_INT32_INT32 &mapAttrReward, int32_t level);							//获取活动收集任务基础奖励
	uint32_t					GetActRandBoxReward(int32_t loopCount);														//获取活动收集任务随机宝箱奖励 
	//副业任务
	void						GetDeputyBaseReward(MAP_INT32_INT32 &mapAttrReward, int32_t level, int32_t loopCount, uint32_t itemId);						//获取副业任务基础奖励
	int32_t					    GetDeputyRewardMulti(int32_t loopCount);													//获取副业任务多倍奖励的倍率
	//打图任务
	void						GetTreasureBaseReward(MAP_INT32_INT32 &mapAttrReward);										//获取打图任务基础奖励
	void						GetTreasureBaseItemReward(uint32_t &itemId, int32_t &num, int8_t &bind);					//获取打图任务基础物品奖励
public://赏金任务
	uint32_t					GetBountyMissionBaseConfig(std::string parmeter);											//获取赏金任务配置
	void						GetBountyMissionInfo(bool bFreeFresh, MissionTrack *pMissionTrack,int32_t loopCount);

private:
	MAP_INT32_SET_UINT32							_dymissionTypeMap;					//动态任务类型map
	DyMissionInfoMap								_dymissionInfoMap;					//动态任务配置
	DyCondtionInfoMap								_dycondtionInfoMap;					//动态条件配置
	MAP_UINT64_SET_UINT32							_dymissionTextMap;					//动态任务前端显示配置
	MissionInfoMap									_missionInfoMap;					//任务配置列表
	MissionChapterInfoMap							_missionChapterMap;					//任务章节配置
	MissionListMap									_postList;							//后置任务列表
	MAP_UINT32_SET_UINT32							_mapOptionMission;					//分支任务列表
	MAP_UINT32_UINT32								_mapBelongOption;					//任务属于的分支子任务
	SET_INT32										_setAllMissionType;					//所有的任务类型
	WithoutPreConMissionsMap						_withoutPreConMissionsList;			//没有前置任务列表
	Tabal											_tabal;								//任务所在线的第一环任务列表，<missionId, std::set<missionId> >
public:
	ObjectPool<MissionInfo>							*m_pMissionInfoPool;				//任务配置对象分配池 
	ObjectPool<MissionTrack>						*m_pMissionTrackPool;				//已接任务对象分配池
private:
	//任务相关的全局参数
	uint32_t m_BountyFreshItemID;	//赏金任务刷新道具
	uint32_t m_BountyMaxAcceptNum;	//赏金任务最大接取次数
private:
	//完成任务会触发外部系统的动作，比如增加活跃度，完成成就等等，这里的map对应 任务配置中的外部类型（key） - 对应系统的类型
	MAP_INT32_INT32 _triggerHuoyue;
	///////////////////////////////// 以下是动态任务随机需要用到的参数 /////////////////////////////////////////
	SET_UINT32 m_setDyMap; //记录动态任务条件用到的地图
	//mapid - paramtype - npcid set
	MAP_UINT32_MAP_INT32_SET_UINT32 m_mapMapNpcParam;//地图NPC参数
	//mapid - paramtype - monsid set
	MAP_UINT32_MAP_INT32_SET_UINT32 m_mapMapMonsParam;//地图怪物参数
	//mapid - paramtype - collect thing set
	MAP_UINT32_MAP_INT32_SET_UINT32 m_mapMapCollectThingParam;//地图使用可采集物件参数
	//mapid - paramtype - use thing set
	MAP_UINT32_MAP_INT32_SET_UINT32 m_mapMapUseThingParam;//地图使用可使用物件参数
	//mapid - paramtype - areaid set
	MAP_UINT32_MAP_INT32_SET_UINT32 m_mapMapAreaParam;//地图区域参数
	//有些怪物没有种在地编中，只有再配置表中，paramtype - monsid set
	MAP_INT32_SET_UINT32  m_mapNoMapMonsParam;
	// areaid set
	SET_UINT32 m_setAllArea; //所有区域集合
	//mapid - paramtype - collect area set
	MAP_UINT32_MAP_INT32_SET_UINT32 m_mapMapCollectAreaParam;//地图采集物区域参数
	//mapid - paramtype - button area set
	MAP_UINT32_MAP_INT32_SET_UINT32 m_mapMapButtonAreaParam;//地图行为按钮区域参数
	//level - set(itemid)
	MAP_UINT32_SET_UINT32 m_mapLevItem;		
	// missiontype - level - itemid(set)
	MAP_UINT32_MAP_UINT32_SET_UINT32 m_mapMissionTypeLevItem;//任务类型等级物品数据
	// missiontype - level - itemid - num
	MAP_INT8_MAP_UINT32_MAP_UINT32_UINT32 m_mapMissionTypeLevItemNum;//任务类型等级物品数量的数据
	// level -equipid(set)
	ORDER_MAP_UINT32_SET_UINT32 m_mapLevEquip;//等级装备数据
	//areaid - collectid set
	MAP_UINT32_SET_UINT32 m_mapAreaToClientCollect;//地图区域对应的前端采集物列表
	//areaid - buttonid set
	MAP_UINT32_SET_UINT32 m_mapAreaToButton;//地图区域对应的行为按钮ID列表
	//collectid - boxid
	MAP_UINT32_SET_UINT32	m_mapCollectToBox;	//采集物对应任务先关的宝箱ID
	//monsterid - boxid set
	MAP_UINT32_SET_UINT32 m_mapMonsToBox;	//动态任务中怪物对应的宝箱ID
};

#define g_MakeMissionManager() (MissionManager::Instance())
#define g_GetMissionManager()  (MissionManager::GetInstance())
#define g_DelMissionManager()  (MissionManager::Destroy())